package com.util;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

public class JxDesCryUtil {

	//void EnCryptDataAndCalAuthCode(unsigned char *ucEnCryptKey,unsigned char *ucAuthKey, unsigned char *ucRandom,unsigned char *inMingWen,unsigned long inLen,unsigned char *outMiWen,unsigned long *outLen);
	/**
	 * Jni加密生成鉴别码
	 * @param keyEncry 认证密钥
	 * @param keyAuth 加密密钥
	 * @param random 随机数
	 * @param mingwen 明文数据
	 * @return 密文数据
	 */
	public native byte[] JniEnCryptDataAndCalAuthCode(byte[] keyEncry, byte[] keyAuth,byte[] random, byte[] mingwen);



	static {
		System.loadLibrary("JxDesCryUtil");
	}

	public static JxDesCryUtil jxCryUtil = new JxDesCryUtil();
	// public static IDEAUtil idea = new IDEAUtil();
	/**
	 * 用于建立十六进制字符的输出的小写字符数组
	 */
	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	/**
	 * 用于建立十六进制字符的输出的大写字符数组
	 */
	private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	/**
	 * 将字节数组转换为十六进制字符数组
	 *
	 * @param data
	 *            byte[]
	 * @return 十六进制char[]
	 */
	public static char[] encodeHex(byte[] data) {
		return encodeHex(data, true);
	}

	/**
	 * 将字节数组转换为十六进制字符数组
	 *
	 * @param data
	 *            byte[]
	 * @param toLowerCase
	 *            <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
	 * @return 十六进制char[]
	 */
	public static char[] encodeHex(byte[] data, boolean toLowerCase) {
		return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}

	/**
	 * 将字节数组转换为十六进制字符数组
	 *
	 * @param data
	 *            byte[]
	 * @param toDigits
	 *            用于控制输出的char[]
	 * @return 十六进制char[]
	 */
	protected static char[] encodeHex(byte[] data, char[] toDigits) {
		int l = data.length;
		char[] out = new char[l << 1];
		// two characters form the hex value.
		for (int i = 0, j = 0; i < l; i++) {
			out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
			out[j++] = toDigits[0x0F & data[i]];
		}
		return out;
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 *
	 * @param data
	 *            byte[]
	 * @return 十六进制String
	 */
	public static String encodeHexStr(byte[] data) {
		return encodeHexStr(data, true);
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 *
	 * @param data
	 *            byte[]
	 * @param toLowerCase
	 *            <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
	 * @return 十六进制String
	 */
	public static String encodeHexStr(byte[] data, boolean toLowerCase) {
		return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 *
	 * @param data
	 *            byte[]
	 * @param toDigits
	 *            用于控制输出的char[]
	 * @return 十六进制String
	 */
	protected static String encodeHexStr(byte[] data, char[] toDigits) {
		return new String(encodeHex(data, toDigits));
	}

	/**
	 * 将十六进制字符数组转换为字节数组
	 *
	 * @param data
	 *            十六进制char[]
	 * @return byte[]
	 * @throws RuntimeException
	 *             如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
	 */
	public static byte[] decodeHex(char[] data) {

		int len = data.length;

		if ((len & 0x01) != 0) {
			throw new RuntimeException("Odd number of characters.");
		}

		byte[] out = new byte[len >> 1];

		// two characters form the hex value.
		for (int i = 0, j = 0; j < len; i++) {
			int f = toDigit(data[j], j) << 4;
			j++;
			f = f | toDigit(data[j], j);
			j++;
			out[i] = (byte) (f & 0xFF);
		}

		return out;
	}

	// char转byte
	private byte[] getBytes(char[] chars) {
		Charset cs = Charset.forName("UTF-8");
		CharBuffer cb = CharBuffer.allocate(chars.length);
		cb.put(chars);
		cb.flip();
		ByteBuffer bb = cs.encode(cb);

		return bb.array();
	}

	// byte转char
	private char[] getChars(byte[] bytes) {
		Charset cs = Charset.forName("UTF-8");
		ByteBuffer bb = ByteBuffer.allocate(bytes.length);
		bb.put(bytes);
		bb.flip();
		CharBuffer cb = cs.decode(bb);

		return cb.array();
	}

	/**
	 * 将Hex字符串转换成ASCI字符串
	 *
	 * @param strHex
	 * @return
	 * @throws Exception
	 */
	public static String HexToAsciSting(String strHex) throws Exception {
		byte[] bytes = StringToBytes(strHex);
		String strAsci = new String(bytes, "GBK");
		return strAsci;
	}

	/**
	 * 将一个ASCI字符串转成HEX字符串
	 *
	 * @param strAsci
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String AsciToHexString(String strAsci)
			throws UnsupportedEncodingException {
/*		TaskExcuteTimeCutter taskExcuteTimeCutter = new TaskExcuteTimeCutter("明文转hex->明文转字节", strAsci.length());
		taskExcuteTimeCutter.start();*/
		byte[] bytes = strAsci.getBytes("GBK");// e4baac413132333435000000
/*		taskExcuteTimeCutter.end();*/

		// for (int i = 0; i < bytes.length; i++)
		// strHex += Integer.toHexString(bytes[i] & 0xff);
		// strHex.toLowerCase();

/*		TaskExcuteTimeCutter taskExcuteTimeCutter2 = new TaskExcuteTimeCutter("明文转hex->字节转HEX", bytes.length);
		taskExcuteTimeCutter2.start();*/
		String hexToString = HexToString(bytes);
/*		taskExcuteTimeCutter2.end();*/

		return hexToString;
	}

	/**
	 * 将一个ASCI字符串转成HEX字符串,限定长度
	 *
	 * @param strAsci
	 * @param nLen长度限定
	 *            ,不足的补字符0
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String AsciToHexString(String strAsci, int nLen)
			throws UnsupportedEncodingException {
		String s = String.valueOf(strAsci);
		byte[] bytes = s.getBytes("GBK");// e4baac413132333435000000
		String strResult = HexToString(bytes);
		int strLen = strResult.length();
		if (strLen >= nLen)
			strResult = strResult.substring(0, nLen);
		else {
			int nAddLen = nLen - strLen;
			for (int i = 0; i < nAddLen; i++)
				strResult += "0";
		}

		return strResult;
	}

	public static String HexToString(byte[] inHex) {
		int i;
		StringBuilder sb = new StringBuilder();
		for (i = 0; i < inHex.length; i++) {
			sb.append(String.valueOf(DIGITS_UPPER[(0xF0 & inHex[i]) >>> 4])+ String.valueOf(DIGITS_UPPER[inHex[i] & 0x0F]));
		}
		return sb.toString();
	}

	/**
	 * 1字节转成2个字符串十六进制字符串
	 *
	 * @param dec
	 * @return
	 */
	public static String ByteToString(byte dec) {
		return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])
				+ String.valueOf(DIGITS_UPPER[dec & 0x0F]);
	}

	public static String ByteToString(int dec) {
		return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])
				+ String.valueOf(DIGITS_UPPER[dec & 0x0F]);
	}

	/**
	 * 2个字符十六进制字符串转成byte
	 *
	 * @param str
	 * @return
	 */
	public static byte StringToByte(String str) {
		return (byte) Integer.parseInt(str, 16);
	}

	public static byte[] LongToHex(int inLong, int nLen, int flagOb) {
		int i = 0;
		byte[] outHex = new byte[nLen];
		for (i = 0; i < nLen; i++) {
			if (flagOb != 0)
				outHex[nLen - 1 - i] = (byte) (inLong >> (8 * (nLen - 1 - i)));
			else
				outHex[i] = (byte) (inLong >> (8 * (nLen - 1 - i)));
		}
		return outHex;

	}

	/**
	 * 整形字符串转成十六进制字符串
	 *
	 * @param str
	 * @param nLimitLen
	 *            转换后字符的长度,必须是2的整数倍
	 * @return
	 */
	public static String IntStringToHexString(String str, int nLimitLen) {
		int nValue = Integer.parseInt(str);
		int nLen = nLimitLen / 2;
		byte[] hexs = LongToHex(nValue, nLen, 0);
		String strResult = HexToString(hexs);
		return strResult;
	}

	/**
	 * 将字符串转成byte[]
	 *
	 * @param str
	 * @return
	 */
	public static byte[] StringToBytes(String str) {
		int nLen = str.length();
		byte bytes[] = new byte[str.length() / 2];
		for (int i = 0; i < nLen / 2; i++) {
			bytes[i] = StringToByte(str.substring(i * 2, i * 2 + 2));
		}
		return bytes;
	}

	/**
	 * 将字符串补80后转成byte[]
	 *
	 * @param str
	 * @return
	 */
	public static byte[] StringToBytes80(String str, int flagMac) {
		String str80 = str;
		int nLen = str.length();
		int add80Len = 8;

		if ((nLen / 2 % 8) != 0)
			add80Len = 8 - (nLen / 2 % 8);
		if (flagMac == 0) {
			if ((add80Len == 8))
				add80Len = 0;
		}

		for (int i = 0; i < add80Len; i++) {
			if (i == 0)
				str80 += "80";
			else
				str80 += "00";
		}
		nLen = str80.length() / 2;
		byte bytes[] = new byte[nLen];
		for (int i = 0; i < nLen; i++) {
			bytes[i] = StringToByte(str80.substring(i * 2, i * 2 + 2));
		}
		return bytes;
	}

	/**
	 * 补80
	 *
	 * @param str
	 * @param flagMac
	 * @return
	 */
	public static String StringApp80(String str, int flagMac) {
		String str80 = str;
		int nLen = str.length();
		int add80Len = 8;
		if ((nLen / 2 % 8) != 0)
			add80Len = 8 - (nLen / 2 % 8);
		if (flagMac == 0) {
			if ((add80Len == 8))
				add80Len = 0;
		}
		for (int i = 0; i < add80Len; i++) {
			if (i == 0)
				str80 += "80";
			else
				str80 += "00";
		}
		return str80;
	}
	/**
	 * 将十六进制字符转换成一个整数
	 *
	 * @param ch
	 *            十六进制char
	 * @param index
	 *            十六进制字符在字符数组中的位置
	 * @return 一个整数
	 * @throws RuntimeException
	 *             当ch不是一个合法的十六进制字符时，抛出运行时异常
	 */
	protected static int toDigit(char ch, int index) {
		int digit = Character.digit(ch, 16);
		if (digit == -1) {
			throw new RuntimeException("Illegal hexadecimal character " + ch
					+ " at index " + index);
		}
		return digit;
	}
	/**
	 * 产生字节随机数
	 *
	 * @param numByte
	 *            字节个数
	 * @return
	 */
	public static String GetRand(int numByte) {
		// (int)(Math.Random()*n)
		String strRandom = new String();
		strRandom = "";
		for (byte i = 0; i < numByte; i++)
			strRandom += ByteToString((byte) ((int) (Math.random() * 255)));
		return strRandom;
	}

	/**
	 * java加密生成鉴别码
	 * @param strKeyCrypt加密密钥
	 * @param strKeyAuth认证密钥
	 * @param strMingWenData明文数据（不需要补80）
	 * @return 密文数据
	 */
	public static String JavaEnCryptDataAndCalAuthCode(String strKeyCrypt,String strKeyAuth,String strMingWenData)
	{
		String strMiWenData = new String();
		strMiWenData = "";
		//随机数
		String strRand = "1122334455667788";//GetRand(8);
		byte[] byteKeyCrypt;
		byteKeyCrypt = StringToBytes(strKeyCrypt.substring(0, 32));
		byte[] byteKeyAuth;
		byteKeyAuth = StringToBytes(strKeyAuth.substring(0, 32));
		byte[] byteRandom;
		byteRandom = StringToBytes(strRand.substring(0, 16));
		byte[] byteMingWenData;

	/*	TaskExcuteTimeCutter taskExcuteTimeCutter1 = new TaskExcuteTimeCutter("明文HEX转byte", strMingWenData.length());
		taskExcuteTimeCutter1.start();*/
		byteMingWenData =  StringToBytes(strMingWenData);
/*		taskExcuteTimeCutter1.end();*/

		byte[] bytesResult;
/*		TaskExcuteTimeCutter taskExcuteTimeCutter2 = new TaskExcuteTimeCutter("得到加密byte", byteMingWenData.length);
		taskExcuteTimeCutter2.start();*/
		bytesResult = jxCryUtil.JniEnCryptDataAndCalAuthCode(byteKeyCrypt, byteKeyAuth, byteRandom, byteMingWenData);
/*		taskExcuteTimeCutter2.end();*/

		/*TaskExcuteTimeCutter taskExcuteTimeCutter3 = new TaskExcuteTimeCutter("密文byte转hex", bytesResult.length);
		taskExcuteTimeCutter3.start();*/
		strMiWenData = HexToString(bytesResult);
	/*	taskExcuteTimeCutter3.end();*/

		return strMiWenData;
	}
}
